package sui.utils.email;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;

import microsoft.exchange.webservices.data.core.ExchangeService;
import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
import microsoft.exchange.webservices.data.core.enumeration.property.BodyType;
import microsoft.exchange.webservices.data.core.enumeration.property.WellKnownFolderName;
import microsoft.exchange.webservices.data.core.enumeration.search.LogicalOperator;
import microsoft.exchange.webservices.data.core.enumeration.service.ConflictResolutionMode;
import microsoft.exchange.webservices.data.core.exception.service.local.ServiceLocalException;
import microsoft.exchange.webservices.data.core.service.folder.Folder;
import microsoft.exchange.webservices.data.core.service.item.EmailMessage;
import microsoft.exchange.webservices.data.core.service.item.Item;
import microsoft.exchange.webservices.data.core.service.schema.EmailMessageSchema;
import microsoft.exchange.webservices.data.credential.ExchangeCredentials;
import microsoft.exchange.webservices.data.credential.WebCredentials;
import microsoft.exchange.webservices.data.property.complex.MessageBody;
import microsoft.exchange.webservices.data.search.FindItemsResults;
import microsoft.exchange.webservices.data.search.ItemView;
import microsoft.exchange.webservices.data.search.filter.SearchFilter;
import sui.utils.logs.LogUtils;

/**
 * <p>
 * Description: EWS邮件操作
 * <p>
 * 
 * @author XQF SUI
 *         <p>
 *         Create Date: 2015年8月26日 下午3:46:53
 *         <p>
 * @version 1.0
 */
public class EWSReaderMailUtils {
	
    private static Logger logger = LogUtils.get();
	
	// 邮件服务器
	private static final String MAIL_SERVER = "email.creditease.cn";
	// 用户名
	private static final String USERNAME = "VIPclub@creditease.cn";
//	private static final String USERNAME = "v-suigaopeng@creditease.cn";
	//邮箱密码
	private static final String PASSWORD = "xqf@8523";
//	private static final String PASSWORD = "xqfsui@2016";
	
	private static ExchangeService service;
	
	/**
	 * <p>
	 * 初始化连接
	 * </p>
	 * 
	 * @author XQF SUI
	 * @created 2015年8月26日 下午3:47:32
	 */
	private static boolean initMailConnection() {
		logger.info("开始初始化邮箱设置...");
		
		// 设置ExchangeService版本为2007SP1
		service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
		// 参数是用户名,密码
		ExchangeCredentials credentials = new WebCredentials(USERNAME, PASSWORD);
		service.setCredentials(credentials);
		try {
			// 设置Exchange Server的URL
			service.setUrl(new URI("https://" + MAIL_SERVER + "/ews/exchange.asmx"));
		} catch (URISyntaxException e) {
			logger.error("初始化邮箱设置失败", e);
			return false;
		}
		
		return true;
	}
	
	/**
	 * <p>
	 * 发邮件
	 * </p>
	 * 
	 * @author XQF SUI
	 * @created 2015年8月26日 下午5:18:02
	 * @param subject 邮件主题
	 * @param to 收件人
	 * @param bodyText 邮件内容
	 * @return
	 */
	public static boolean doSendMail(String subject, List<String> to, String bodyText) {
		return doSendMail(subject, to, null, bodyText, null);
	}
	
	/**
	 * <p>
	 * 发邮件
	 * </p>
	 * 
	 * @author XQF SUI
	 * @created 2015年8月26日 下午5:18:02
	 * @param subject 邮件主题
	 * @param to 收件人
	 * @param bodyText 邮件内容
	 * @param realPath 附件
	 * @return
	 */
	public static boolean doSendMail(String subject, List<String> to, String bodyText, String realPath) {
		return doSendMail(subject, to, null, bodyText, realPath);
	}
	
	/**
	 * <p>
	 * 发邮件
	 * </p>
	 * 
	 * @author XQF SUI
	 * @created 2015年8月26日 下午5:18:02
	 * @param subject 邮件主题
	 * @param to 收件人
	 * @param bodyText 邮件内容
	 * @param realPath 附件
	 * @return
	 */
	public static boolean doSendMail(String subject, String to, String bodyText, String realPath) {
		List<String> mailList = new ArrayList<String>();
		mailList.add(to);
		return doSendMail(subject, mailList, null, bodyText, realPath);
	}
	
	/**
	 * <p>
	 * 发邮件
	 * </p>
	 * 
	 * @author XQF SUI
	 * @created 2015年8月26日 下午5:18:02
	 * @param subject 邮件主题
	 * @param to 收件人
	 * @param bodyText 邮件内容
	 * @param realPath 附件
	 * @return
	 */
	public static boolean doSendMail(String subject, List<String> to, List<String> cc, String bodyText) {
		return doSendMail(subject, to, cc, bodyText, null);
	}
	
	/**
	 * <p>
	 * 使用Exchange协议发送邮件
	 * </p>
	 * 
	 * @author XQF SUI
	 * @created 2015年8月26日 下午3:51:14
	 * @param subject 邮件主题
	 * @param to 收件人
	 * @param cc 抄送
	 * @param bodyText 正文
	 * @param realPath 附件
	 * @throws Exception
	 */
	public static boolean doSendMail(String subject, List<String> to, List<String> cc, String bodyText, String realPath) {
		logger.info("开始发送邮件...");
		try {
			// 判断邮件服务器连接是否正常
			if (service == null) {
				if (!initMailConnection())
					return false;
			}
			
			EmailMessage msg = new EmailMessage(service);
			
			// 设置主题
			msg.setSubject(subject);
			
			// 设置内容
			MessageBody body = MessageBody.getMessageBodyFromText(bodyText);
			body.setBodyType(BodyType.HTML);
			msg.setBody(body);
			
			// 设置收件人
			for (String s : to) {
				msg.getToRecipients().add(s);
			}
			
			// 设置抄送人
			if (cc != null && cc.size() > 0) {
				for (String s : cc) {
					msg.getCcRecipients().add(s);
				}
			}
			
			// 设置附件
			if (realPath != null && !"".equals(realPath)) {
				msg.getAttachments().addFileAttachment(realPath);
			}
			
			// 发送邮件
			msg.send();
		} catch (Exception e) {
			logger.error("邮件发送失败", e);
			return false;
		}
		
		logger.info("邮件发送成功！");
		return true;
	}
	
	/**
	 * <p>
	 * 使用Exchange协议接收邮件
	 * </p>
	 * 
	 * @author XQF SUI
	 * @created 2015年8月26日 下午4:14:55 isRead 是否已读    true:已读   false:未读 
	 * @throws Exception
	 */
	private static List<Item> getUnreadEmails(Boolean isRead, Date startDate, Date endDate) throws Exception {
		// 设置读取条数
		ItemView itemView = new ItemView(Integer.MAX_VALUE);
		
		// 判断邮件服务器连接是否正常
		if (service == null) {
			if(!initMailConnection()) return null;
		}
		
		// 查找Inbox,加入过滤器条件
		FindItemsResults<Item> unRead = Folder.bind(service, WellKnownFolderName.Inbox).findItems(mailFilter(isRead, startDate, endDate),
				itemView);
		
		return unRead.getItems();
	}
	
	/**
	 * <p>
	 * 设置获取什么类型的邮件
	 * </p>
	 * 
	 * @author XQF SUI
	 * @created 2015年8月26日 下午5:10:52
	 * @param isRead 是否已读 true:已读 false:未读
	 * @return
	 */
	private static SearchFilter mailFilter(Boolean isRead, Date startDate, Date endDate) {
		List<SearchFilter> searchFilters = new ArrayList<SearchFilter>();
		// 设置是否已读
		searchFilters.add(new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, isRead == null ? false : isRead));
		
		if (startDate != null) {
			searchFilters.add(new SearchFilter.IsGreaterThanOrEqualTo(EmailMessageSchema.DateTimeCreated, startDate));
		}
		
		if (endDate != null) {
			searchFilters.add(new SearchFilter.IsLessThanOrEqualTo(EmailMessageSchema.DateTimeCreated, endDate));
		}
		
		return new SearchFilter.SearchFilterCollection(LogicalOperator.And, searchFilters);
	}
	
	/**
	 * <p>
	 * 设置邮件为已读
	 * </p>
	 * @author XQF SUI
	 * @created 2015年8月26日 下午5:41:55
	 * @return
	 */
	private static boolean setMailAsRead(Item item) {
		logger.info("开始设置邮件为已读...");
		
		// 判断邮件服务器连接是否正常
		if (service == null) {
			if(!initMailConnection()) return false;
		}
		
		try {
			 EmailMessage message = EmailMessage.bind(service, item.getId());
             message.setIsRead(true); 
             message.update(ConflictResolutionMode.AlwaysOverwrite);
		} catch (Exception e) {
			logger.error("设置为已读失败", e);
			return false;
		}
		
		return true;
	}
	
	/**
	 * <p>
	 * 获取未送达的邮件
	 * </p>
	 * 
	 * @author XQF SUI
	 * @created 2015年8月26日 下午5:23:48
	 * @return
	 * @throws Exception
	 */
	public static List<Item> getNonDeliveryMail(Boolean isRead, Date startDate, Date endDate) throws Exception {
		List<Item> list = new ArrayList<Item>(); 
		
		// 遍历获取到的邮件
		for (Item item : getUnreadEmails(isRead, startDate, endDate)) {
			System.out.println(item.getSubject());
			if (item.getSubject() != null) {
				if (item.getSubject().toString().contains("未送达") 
						|| item.getSubject().toString().contains("Delivery Status")
						|| item.getSubject().toString().contains("退信")) {
					list.add(item);
				}
			}
		}
		
		return list;
	}
	
	/**
	 * <p>
	 * 设置未送达邮件为已读
	 * </p>
	 * @author XQF SUI
	 * @created 2015年8月26日 下午7:01:27
	 * @param subject	邮件主题
	 * @param isLike 	是否采用模糊匹配
	 * @return
	 */
	public static boolean setNonDeliveryMailAsRead(Date startDate, Date endDate) {
		
		try {
			for (Item item : getNonDeliveryMail(false, startDate, endDate)) {
				setMailAsRead(item);
			}
		} catch (Exception e) {
			logger.error("设置未送达邮件为已读失败", e);
			return false;
		}
		
		return true;
	}
	
	public boolean setMailAsReadByName(String subject, Boolean isLike, Date startDate, Date endDate) {
		try {
			for (Item item : getUnreadEmails(false, startDate, endDate)) {
				if (isLike == true ? item.getSubject().contains(subject) : item.getSubject().equals(subject)) {
					System.out.println(item.getSubject());
					System.out.println(item.getDisplayTo());
					System.out.println(item.getDateTimeCreated());
					setMailAsRead(item);
				}
				
			}
		} catch (Exception e) {
			logger.error("");
		}
		
		return true;
	}
	
	/**
	 * <p>
	 * 从未送达的邮件中获取接收方邮箱地址
	 * </p>
	 * @author XQF SUI
	 * @created 2015年10月15日 下午3:13:10
	 * @param item
	 * @return
	 */
	public static String getMailAddrFormMessage(Item item) {
		String mailAddr = null;
		
		try {
			EmailMessage message = EmailMessage.bind(service, item.getId());
			
			if (message != null) {
				MessageBody messageBody = message.getBody();
				
				if (messageBody != null && StringUtils.isNotBlank(message.getBody().toString())) {
					String mailContent = message.getBody().toString();
					
					if ("Text".equals(message.getBody().getBodyType().toString())) {
						mailAddr = mailContent.substring(mailContent.indexOf("<") + 1, mailContent.indexOf(">"));
					} else if ("HTML".equals(message.getBody().getBodyType().toString())) {
						if (item.getSubject().equals("未送达: 联办财经研究院座谈会报告")) {
							mailAddr = mailContent.substring(mailContent.indexOf("<a href=\"mailto:")).substring(16,
									mailContent.substring(mailContent.indexOf("<a href=\"mailto:")).indexOf("\">"));
						} else if (mailContent.indexOf("您的邮件被收件人（") > -1) {
							mailAddr = mailContent.substring(mailContent.indexOf("您的邮件被收件人（") + 9,
									mailContent.indexOf("）的反垃圾设置拒收，邮件无法送达。"));
						} else {
							mailAddr = mailContent.substring(mailContent.indexOf("<a href=\"mailto:") + 16).substring(0, 
									mailContent.substring(mailContent.indexOf("<a href=\"mailto:") + 16).indexOf("\">"));
						}
					}
				}
			}
		} catch (ServiceLocalException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return mailAddr;
	}
	
	@SuppressWarnings("deprecation")
	public static Date createDate(int year, int month, int day) {
		return new Date(year - 1900, month - 1, day);
	}
	
	public static void main(String[] args) throws Exception {
		// ---------------------- 设置未读邮件为已读 ----------------------
//		setNonDeliveryMailAsRead();
		
		// ---------------------- 获取未读邮件 ----------------------
		List<Item> list = getNonDeliveryMail(true, createDate(2017, 7, 4), null);
		
		for (Item item : list) {
			System.out.println(getMailAddrFormMessage(item));
		}
		
//		System.out.println(new Date(2017 - 1900, 4, 1));
		
//		System.out.println(getUnreadEmails(true, createDate(2017, 5, 1), null).size())
	}
}
